﻿using System;
using System.Drawing;
using System.IO;
using System.IO.Compression;
using System.Text;
using System.Threading.Tasks;

namespace oueb.helpers
{
    internal partial class helper
    {
        public static async Task<Stream> GetGzipStream(Stream stream)
        {
            using var mem = new MemoryStream();
            using (var ms = new GZipStream(mem, CompressionLevel.Fastest, true)) await stream.CopyToAsync(ms, 81920);
            await mem.FlushAsync();
            mem.Position = 0;
            return mem;
        }
        public static async Task<Stream> GetGzipStream(byte[] data)
        {
            using var mem = new MemoryStream();
            using (var ms = new GZipStream(mem, CompressionLevel.Fastest, true)) await ms.WriteAsync(data, 0, data.Length);
            await mem.FlushAsync();
            mem.Position = 0;
            return mem;
        }
        public static readonly byte[] chunk_split = [ 13, 10 ];
        public const byte chunk_zore = 48;
        public static async Task SendChunk_Stream(Stream origin, Stream sender, int bufsize = 32768)
        {
            var buf = new byte[bufsize];
            int size = -1;

            if (origin.Length != 0)
            while (true)
            {
                size = await origin.ReadAsync(buf, 0, bufsize);
                if (size == 0) break;
                sender.Write(Encoding.ASCII.GetBytes(size.ToString("x")));
                sender.Write(chunk_split);
                sender.Write(buf, 0, size);
                await sender.WriteAsync(chunk_split);
            }
            sender.WriteByte(chunk_zore);
            sender.Write(chunk_split);
            sender.Write(chunk_split);
            await sender.FlushAsync();
        }
        public static async Task SendChunk_GzipStream(Stream nocompress, Stream sender, int bufsize = 32768)
        {
            var buf = new byte[bufsize];
            int size =-1;
            int size2 = -1;

            if (nocompress.Length != 0)
            using (var mem = new MemoryStream())
            using (var ms = new GZipStream(mem, CompressionLevel.Fastest, true))
            while (true)
            {
                size = await nocompress.ReadAsync(buf, 0, bufsize);
                if (size == 0) break;
                mem.Position = 0;
                await ms.WriteAsync(buf, 0, size);
                await ms.FlushAsync();
                if (mem.Length == 0) continue;
                sender.Write(Encoding.ASCII.GetBytes(mem.Position.ToString("x")));
                sender.Write(chunk_split);
                size2 = (int)mem.Position;
                mem.Position = 0;
                for (; bufsize - size2 < 0; size2 -= size) sender.Write(buf, 0, size = mem.Read(buf, 0, bufsize));
                if (size2 > 0) sender.Write(buf, 0, mem.Read(buf, 0, size2));
                await sender.WriteAsync(chunk_split);
            }
            sender.WriteByte(chunk_zore);
            sender.Write(chunk_split);
            sender.Write(chunk_split);
            await sender.FlushAsync();
        }
        public static async Task SendChunk_DeflateStream(Stream nocompress, Stream sender, int bufsize = 32768)
        {
            var buf = new byte[bufsize];
            int size =-1;
            int size2 =-1;

            if (nocompress.Length != 0)
            using (var mem = new MemoryStream())
            using (var ms = new DeflateStream(mem, CompressionLevel.Fastest, true))
            while (true)
            {
                size = await nocompress.ReadAsync(buf, 0, bufsize);
                if (size == 0) break;
                mem.Position = 0;
                await ms.WriteAsync(buf, 0, size);
                await ms.FlushAsync();
                if (mem.Length == 0) continue;
                sender.Write(Encoding.ASCII.GetBytes(mem.Position.ToString("x")));
                sender.Write(chunk_split);
                size2 = (int)mem.Position;
                mem.Position = 0;
                for (; bufsize - size2 < 0; size2 -= size) sender.Write(buf, 0, size = mem.Read(buf, 0, bufsize));
                if (size2 > 0) sender.Write(buf, 0, mem.Read(buf, 0, size2));
                await sender.WriteAsync(chunk_split);
            }
            sender.WriteByte(chunk_zore);
            sender.Write(chunk_split);
            sender.Write(chunk_split);
            await sender.FlushAsync();
        }
    }
}
